/*
 * Copyright 2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.gradle.api.internal.tasks.testing.failure.mappers

import org.opentest4j.AssertionFailedError
import org.opentest4j.FileInfo
import org.opentest4j.ValueWrapper
import spock.lang.Specification

import java.nio.charset.StandardCharsets

class OpenTestAssertionFailedMapperTest extends Specification {

    private static final FileInfo ACTUAL_CUSTOM_FILE_INFO = new CustomFileInfo("actual_custom_file", "actual_custom_content")
    private static final FileInfo EXPECTED_CUSTOM_FILE_INFO = new CustomFileInfo("expected_custom_file", "expected_custom_content")

    private static final FileInfo ACTUAL_FILE_INFO = new FileInfo("actual_file", "actual_content".getBytes(StandardCharsets.UTF_8))
    private static final FileInfo EXPECTED_FILE_INFO = new FileInfo("expected_file", "expected_content".getBytes(StandardCharsets.UTF_8))

    private static final ValueWrapper ACTUAL_STRING_VALUE_WRAPPER = ValueWrapper.create("actual_value")
    private static final ValueWrapper EXPECTED_STRING_VALUE_WRAPPER = ValueWrapper.create("expected_value")

    private static final ValueWrapper ACTUAL_INT_VALUE_WRAPPER = ValueWrapper.create(1)
    private static final ValueWrapper EXPECTED_INT_VALUE_WRAPPER = ValueWrapper.create(2)

    private static class CustomFileInfo extends FileInfo {
        CustomFileInfo(String path, String contents) {
            super(path, contents.getBytes(StandardCharsets.UTF_8))
        }
    }

    def "can map null expected values"() {
        given:
        def mapper = new OpenTestAssertionFailedMapper()
        def error = new AssertionFailedError("message", suppliedExpected, suppliedActual)

        when:
        def failure = mapper.map(error, null)

        then:
        failure.details.expected == expectedExpected
        failure.details.expectedContent == expectedExpectedContent
        failure.details.actual == expectedActual
        failure.details.actualContent == expectedActualContent

        where:
        // How this works is that the test will execute all combinations of the two triples,
        // but won't change the order of the elements in each triple.
        //
        // E.g.: [null, null, null], ["actual", "actual", null] => [null, null, null, "actual", "actual", null]
        [suppliedActual, expectedActual, expectedActualContent, suppliedExpected, expectedExpected, expectedExpectedContent] << [
            [
                [null, null, null],
                ["actual", "actual", null],
                [ACTUAL_CUSTOM_FILE_INFO, ACTUAL_CUSTOM_FILE_INFO.path, ACTUAL_CUSTOM_FILE_INFO.contents],
                [ACTUAL_FILE_INFO, ACTUAL_FILE_INFO.path, ACTUAL_FILE_INFO.contents],
                [ACTUAL_STRING_VALUE_WRAPPER, ACTUAL_STRING_VALUE_WRAPPER.value, null],
                [ACTUAL_INT_VALUE_WRAPPER, ACTUAL_INT_VALUE_WRAPPER.value.toString(), null]
            ],
            [
                [null, null, null],
                ["expected", "expected", null],
                [EXPECTED_CUSTOM_FILE_INFO, EXPECTED_CUSTOM_FILE_INFO.path, EXPECTED_CUSTOM_FILE_INFO.contents],
                [EXPECTED_FILE_INFO, EXPECTED_FILE_INFO.path, EXPECTED_FILE_INFO.contents],
                [EXPECTED_STRING_VALUE_WRAPPER, EXPECTED_STRING_VALUE_WRAPPER.value, null],
                [EXPECTED_INT_VALUE_WRAPPER, EXPECTED_INT_VALUE_WRAPPER.value.toString(), null]
            ]
        ].combinations { actual, expected ->
            // Make a single array out of the two arrays incoming
            actual + expected
        }
    }

}
